<template>
  <div class="container">
    <!-- left-arrow：左侧的箭头
         @click-left：单击左侧箭头的事件处理
    -->
    <van-nav-bar title="搜索中心" left-arrow @click-left="$router.back()" />
    <!-- 搜索输入框 -->
    <!-- v-model：双向数据绑定，获得、设置 表单域搜索的关键内容 van-search组件提供的 -->
    <!-- @search:搜索框中点击“回车按钮”时会触发的事件  是van-search组件提供的事件 -->
    <van-search v-model.trim="searchText" placeholder="请输入搜索关键词" @search="onSearch(searchText)" />
    <!-- 及时联想数据 -->
    <van-cell-group v-if="suggestionList.length>0">
      <!-- van-cell搜索的组件标签   title：单元格标题内容   icon：单元格项目前边的图标 -->
      <van-cell
        :title="item"
        icon="search"
        v-for="(item,k) in suggestionList"
        :key="k"
        @click="onSearch(item)"
      >
        <!-- 因为要使用methods方法，并且该方法返回的信息里边有html标签和css样式
             所以，不要直接使用title属性，要使用命名插槽，内部结合v-html做应用
             v-html:可以识别html结构 相当于js中的innerHTML
             如果内容中，没有html标签和css样式，就可以对van-cell单元格的title属性直接操作
        -->
        <div slot="title" v-html="highLightCell(item,searchText)"></div>
      </van-cell>
    </van-cell-group>
    <!-- 历史联想数据 -->
    <van-cell-group v-else>
      <!-- 联想历史记录管理 -->
      <van-cell title="历史记录">
        <!-- 删除图标
      slot="right-icon" 命名插槽 给 cell单元格的右边显示内容(垃圾桶图标)
      name="delete" 垃圾桶图标
      style="line-height:inherit" 设置内容高度与父级一致
        -->
        <van-icon
          @click="isDeleteData=true"
          v-show="!isDeleteData"
          slot="right-icon"
          name="delete"
          style="line-height:inherit"
        ></van-icon>
        <div v-show="isDeleteData">
          <span style="margin-right:10px" @click="suggestDelAll()">全部删除</span>
          <span @click="isDeleteData=false">完成</span>
        </div>
      </van-cell>

      <!-- 历史联想项目数据展示 -->
      <van-cell :title="item" v-for="(item,k) in sugguestHistories" :key="k">
        <!-- 删除按钮 -->
        <van-icon
          v-show="isDeleteData"
          slot="right-icon"
          name="close"
          style="line-height:inherit"
          @click="suggestDel(k)"
        ></van-icon>
      </van-cell>
    </van-cell-group>
  </div>
</template>

<script>
// 导入搜索的 联想关键字 的api函数
import { apiSearchSuggestion } from '@/api/search.js'

// 创建常量，配置历史关键字的key名称
const SH = 'sugguest-histories'

export default {
  name: 'search-index',
  data () {
    return {
      searchText: '', // 用户输入的搜索关键字
      suggestionList: [], // 联想建议数据列表

      isDeleteData: false, // 历史记录开关

      // 从localStorage里获取已经储存好的关键字的联想历史记录
      sugguestHistories: JSON.parse(localStorage.getItem(SH)) || []
    }
  },
  // 通过使用watch监听器，监听输入框的变化，以实现对关键字的搜索
  watch: {
    searchText: function (newV) {
      // 该监听器每次进来的时候，首先清除this.timer(就是setTimeout停止)定时器
      // 针对this.timer做清除操作，防止定时器累加
      clearTimeout(this.timer)

      if (!newV) {
        // 关键字如果为空，就停止联想获取,并去除旧的联想数据
        this.suggestionList = [] // 清除联想数据
        return false // 用户没有输入信息时，就不用联想了
      }

      // 介入防抖技术
      // 对setTimeout的结果做接收，以便可以中断定时器的执行
      // 返回的是“整形数字”信息
      // this.timer：指的是给当前的data临时声明的一个成员，可以不用注册，组件运行期间都生效
      // 加上this：指的是唯一的timer被使用(即使事件被多次调用)
      this.timer = setTimeout(async () => {
        // 正常联想
        const result = await apiSearchSuggestion(newV)
        // console.log(result)  // {options: Array(5)}
        // 接收数据
        this.suggestionList = result.options
      }, 1000)
    }
  },

  methods: {
    // 1.点击时，跳转到搜索结果页面
    // kw：搜索的关键字
    onSearch (kw) {
      // 应用Set，可以统一对kw关键字做收集储存
      if (!kw) {
        return false // 没有输入关键字时，停止文章检索
      }

      // 把当前的kw关键字储存起来，还要过滤去除重复的
      // 把关键字转坏为Set集合类型
      const st = new Set(this.sugguestHistories)
      // 然后，对Set做添加操作
      st.add(kw)
      // 在把添加好的关键字集合转换为数组集合，并赋予给sugguestHistories
      this.sugguestHistories = Array.from(st)

      // 再重新存储添加后的关键字集合信息到localStorage里
      localStorage.setItem(SH, JSON.stringify(this.sugguestHistories))

      // 路由跳转
      this.$router.push('/search/result/' + kw)
    },

    // 2.关键字高亮设置
    // content:是要高亮设置的目标内容
    // keyWords:目标内容中，要被匹配的关键字
    highLightCell (content, keywords) {
      // 1.创建正则
      // 创建正则对象有两种方式：
      // const reg = /^1[35789]\d{9}$/g
      // const reg = new RegExp('/^1[35789]\d{9}$/','g')
      // i:表示忽略大小写

      // 由于正则主体内容是keywords变量，比较适合使用new RegExp() 方式
      const reg = new RegExp(keywords, 'i')

      // 2.将正则与目标内容进行匹配
      // A.test() 返回是否匹配到的Boolean值
      // B.match() 返回匹配到的结果
      // 因为要获得匹配到的内容，所以使用match()方法
      // 语法：目标内容.match(正则)
      const rst = content.match(reg)
      // console.log(rst)  // 结果：["vue", index: 0, input: "vue本地项目获s", groups: undefined]
      // 结论：
      // rst[0]:就是从目标内容中匹配到的关键字信息 例如:vue
      // rst['index']:关键字出现的下标位置
      // rst['input']:代表完整的目标内容

      // 3.如果目标内容没有匹配到关键字，就不要做高亮了，原样输出即可
      if (rst === null) {
        return content
      }

      // 4.对目标内容的关键字做替换，把“普通”的关键字变为“高亮”的关键字
      // 目标内容.replace(目标关键字，替换内容)
      // 目标内容.replace(正则，rst[0]+样式处理)
      return content.replace(reg, `<span style="color:red;">${rst[0]}</span>`)
    },

    // 3.删除单个的关键字项目
    suggestDel (index) {
      // 页面级的响应效果
      // index:被删除项目在列表数组中的下标
      this.sugguestHistories.splice(index, 1)

      // 持久删除
      localStorage.setItem(SH, JSON.stringify(this.sugguestHistories))
    },

    // 4.删除全部的关键字项目
    suggestDelAll () {
      // 页面级删除
      this.sugguestHistories = []

      // 持久localStorage删除
      localStorage.removeItem(SH)
    }
  }
}
</script>

<style scoped lang='less'></style>
